package com.wxh.bomb.httpserver.server;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

/**
 * 封装请求类
 * @className Request
 * @date 2015年12月4日 上午11:14:31
 * @author <a href="mailto:waferslove@sina.com">王星火</a>
 * @version V1.0
 */
public class Request {
	// 请求方式
	private String method;
	// 请求资源
	private String url;
	// 请求参数
	private Map<String,List<String>> parameters;
	
	// 请求信息
	private String requestInfo;
	
	private static final String CRLF="\r\n";
	
	// 初始化
	private Request() {
		this.method = "";
		this.url = "";
		this.parameters = new HashMap<String, List<String>>();
		this.requestInfo = "";
	}
	
	// 构造方法
	public Request(Socket client){
		this();
		// 读取客户端流信息
		try {
			byte[] data = new byte[20480];
			int length = client.getInputStream().read(data);
			this.requestInfo = new String(data, 0, length).trim();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 分析请求信息
		parseRequestInfo();
	}
	
	// 解析请求信息
	private void parseRequestInfo(){
		// 请求信息判断
		if(null == requestInfo || "".equals(requestInfo = requestInfo.trim())){
			return;
		}
		/**
		 * =========================================================
		 * 从信息的首行分解出 :请求方式    请求路径   请求参数(get可能存在)
		 *   如:GET /index.html?name=123&pwd=5456 HTTP/1.1
		 * 如果为post方式，请求参数可能在 最后正文中
		 * 思路:
		 * 1)请求方式 :找出第一个/  截取即可
		 * 2)请求资源:找出第一个/   HTTP/ 
		 * =========================================================
		 */
		String paramStr =""; //接收请求参数 
		//1、获取请求方式
		String firstLine = requestInfo.substring(0,requestInfo.indexOf(CRLF));
		int idx = requestInfo.indexOf("/"); // /的位置
		this.method = firstLine.substring(0, idx).trim();
		String urlStr = firstLine.substring(idx,firstLine.indexOf("HTTP/")).trim();
		if(this.method.equalsIgnoreCase("post")){
			this.url = urlStr;		
			paramStr = requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
			
		}else if(this.method.equalsIgnoreCase("get")){
			if(urlStr.contains("?")){ //是否存在参数
				String[] urlArray = urlStr.split("\\?");
				this.url = urlArray[0];
				paramStr = urlArray[1];//接收请求参数 
			}else{
				this.url = urlStr;			
			}
		}
		
		//2.解析请求参数
		parseParameters(paramStr);
		
	}
	
	// 解析参数
	private void parseParameters(String paramStr){
		if(null == paramStr || "".equals(paramStr.trim())){
			return;
		}
		// 用&分割字符串
		StringTokenizer token = new StringTokenizer(paramStr, "&");
		while(token.hasMoreTokens()){
			String param = token.nextToken();
			String[] params = param.split("=");
			// 分割后的数组如果长度为1，将数据的长度扩容到2, 防止出现空指针异常
			if(params.length == 1){
				params = Arrays.copyOf(params, 2);
				// 将value设置为null
				params[1] = null;
			}
			// 将key和value分别存入到map中
			String key = params[0];
			List<String> value = new ArrayList<String>();
			value.add(null == params[1] ? null : decode(params[1],"utf-8"));
			if(!parameters.containsKey(key)){
				parameters.put(key, value);
			}
		}
	}
	
	// 解决中文编码的问题
	private String decode(String value, String code) {
		try {
			return URLDecoder.decode(value, code);
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}
	
	// 获取参数(对多个的参数)
	public String[] getParameters(String name){
		List<String> values = parameters.get(name);
		if(values == null){
			return null;
		}else{
			return values.toArray(new String[0]);
		}
	}
	
	// 获取参数(对单一的参数)
	public String getParameter(String name){
		String[] values = getParameters(name);
		if(values == null){
			return null;
		}else{
			return values[0];
		}
	}
	
	public String getUrl(){
		return this.url;
	}
}
